<?php
/**
 * Handles matching of invalid tags in strict manner. If a new tag is opened before a previous tag is closed (invalid nesting), the latter tag will be kept as literal text in the output.
 * 
 * 
 * @package CryoBB/Strategy
 * @author Scott Martin <sjm.dev1[at]gmail[dot]com>, Jonah Dahlquist <jonah[at]nucleussystems[dot]com>
 * @license GNU GPL V3
 */
class CryoBB_Strategy_Strict
{

	// tags passed from Base
	private $tags = array();
	
	// regular expression read from file
	private $regex = null;
	
	/**
	 * @param array $tags
	 */
	public function __construct($tags)
	{
		$this->tags = $tags;
		$this->regex = $this->makeRegex();
	}
	
    /**
     * Matches bb code tags and their contents
     *
     * Recursively matches bb code tags and their contents based on the regexp 
     * in property $matchRegexp.  Recursion is necessary to capture nested bb 
     * code elements.  Stores matches in an array and returns them.
     *
     * @param $str - the string to match for bb code tags
     * @param $offset - the offset of the parent tag
     * @access private
     * @return mixed - array of matches if found, false if no matches found
     */
	public function matchTags($str, $offset = 0)
	{
		if ((strpos($str, '[') === false) || (strpos($str, ']') === false))
		{
			return array();
		}
		
		if (!preg_match_all($this->regex, $str, $matchesResults, PREG_SET_ORDER | PREG_OFFSET_CAPTURE))
		{
			return array();
		}
		
		$matches = array();
		
		foreach ($matchesResults as $match)
		{
			$match = new CryoBB_Match($match, $offset);
			$matches[] = $match;
			
			$newMatches = $this->matchTags($match->content, $match->childOffset());
			$matches = array_merge($matches, $newMatches);
		}
		
		return $matches;
	}
	
	/**
	 * Makes regular expressions
	 *
	 * Makes regular expressions based on the tags supplied via the addTags()
	 * method.  Based on the value of parameter $extract, a regular expression is 
	 * returned to match all tags or the tags to be extracted from the input 
	 * string.  Called from public method make()
	 *
	 * @access private
	 * @return mixed - string regexp when tag list is not empty and/or extraction 
	 *  tags can be found, false if otherwise
	 */
	private function makeRegex()
	{
		$tagList	= array_keys($this->tags);
		$regexp		= '';

		foreach ($tagList AS $tag)
		{
			$regexp .= '|' . preg_quote($tag);
		}
		
		$f = fopen(dirname(__FILE__) . '/strict_regex.txt', 'r');
		$regex_template = rtrim(fgets($f));
		fclose($f);
		
		return (!empty($regexp) === true)
			? sprintf($regex_template, $regexp)
			: false;
	}
}